package com.qicheng.wlhyspider.hainan.conroller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qicheng.wlhyspider.common.*;
import com.qicheng.wlhyspider.hainan.conroller.dto.FinancialDTO;
import com.qicheng.wlhyspider.hainan.entity.FinancialAmountEntity;
import com.qicheng.wlhyspider.hainan.entity.FinancialMasterEntity;
import com.qicheng.wlhyspider.hainan.entity.FinancialShippingNoteEntity;
import com.qicheng.wlhyspider.hainan.mapper.FinancialAmountMapper;
import com.qicheng.wlhyspider.hainan.mapper.FinancialMasterMapper;
import com.qicheng.wlhyspider.hainan.mapper.FinancialShippingNoteMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/hainan/financial")
@Slf4j
public class FinancialController {
    private final FinancialMasterMapper financialMasterMapper;
    private final FinancialAmountMapper financialAmountMapper;
    private final FinancialShippingNoteMapper financialShippingNoteMapper;

    private final RedisUtils redisUtils;

    public FinancialController(FinancialMasterMapper financialMasterMapper, FinancialAmountMapper financialAmountMapper, FinancialShippingNoteMapper financialShippingNoteMapper, RedisUtils redisUtils) {
        this.financialMasterMapper = financialMasterMapper;
        this.financialAmountMapper = financialAmountMapper;
        this.financialShippingNoteMapper = financialShippingNoteMapper;
        this.redisUtils = redisUtils;
    }

    private List<String> shippingIdList = new ArrayList<>();

//    @PostConstruct
//    public void getToken() {
//        log.info("================getToken======================");
//        LoginUtils.login(redisUtils);
//    }
//
//
//    @Scheduled(cron = "0 0/25 * * * ?")
//    public void refreshToken() {
//        log.info("================refreshToken======================");
//        LoginUtils.login(redisUtils);
//    }
    @Scheduled(cron = "0/30 * * * * ?")
    public void queryMenu() {
        // 为了刷新token
//        HttpUtils.httpGet("http://wlhy.mot.gov.cn/hainan/system/home/queryMenu", redisUtils);
    }

    @GetMapping("/saveAll")
    public String saveAll(@RequestParam("page") Integer page, @RequestParam("maxPage") Integer maxPage,
                          @RequestParam("startDate") String startDate, @RequestParam("endDate") String endDate) {
        if (CollectionUtil.isEmpty(shippingIdList)) {
            shippingIdList = financialMasterMapper.selectList(Wrappers.<FinancialMasterEntity>lambdaQuery()
                    .select(FinancialMasterEntity::getId)).stream().map(FinancialMasterEntity::getId).collect(Collectors.toList());
        }
        Integer limit = 1000;
        Integer pages = 32;
//        LoginUtils.login();
        CompletableFuture<Object>[] futures = new CompletableFuture[pages];
        for (int i = 0; i < pages; i++) {
            int finalPage = page + i;
            CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
                try {
                    saveAllPri(finalPage, limit, startDate, endDate);
                    log.info("资金单插入，第{}页成功", finalPage);
                } catch (Exception e) {
                    log.error("资金单插入，第{}页失败", finalPage);
                    log.error(e.getMessage(), e);
                    e.printStackTrace();
                }
                return null;
            });
            futures[i] = future;
        }
        // todo 最好在循环插入的时候也捕获异常
        log.info("====futures.length=={}", futures.length);
        CompletableFuture<Void> cf = CompletableFuture.allOf(futures);

        // 如果执行成功:
        cf.thenAccept((result) -> {
            log.info("资金单插入成功！！！");
            if (page < maxPage) {
                saveAll(page + pages, maxPage, startDate, endDate);
            }

        });
        // 如果执行异常:
        cf.exceptionally((e) -> {
            e.printStackTrace();
            log.info("资金单插入失败！！！");
            return null;
        });
        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        return "资金单插入成功！！！";
    }

//    @GetMapping("/save")
//    public String save(@RequestParam("page") Integer page, @RequestParam("limit") Integer limit, @RequestParam("startDate") String startDate, @RequestParam("endDate") String endDate) {
//        return saveAll(page, limit, startDate, endDate);
//    }

    private String saveAllPri(Integer page, Integer limit, String startDate, String endDate) {
        log.info("开始查询第{}页", page);
        String listUrl = String.format("http://wlhy.mot.gov.cn/hainan/business/financial/list?page=%s&limit=%s&sendToProDateTimeRange=%s+~+%s",
                page, limit, startDate, endDate);
//        String listUrl = String.format("http://wlhy.mot.gov.cn/hainan/business/shipping/list?page=%s&limit=%s&sendToProDateTimeRange=%s+~+%s",
//                page, limit, startDate, endDate);
        HttpResponse httpResponse = HttpUtils.httpGet(listUrl, redisUtils);
        log.info("开始查询第{}页，返回状态{}", page, httpResponse.getStatus());
        if (httpResponse.getStatus() == 200) {
            String body = httpResponse.body();
            PageResult pageResult = JSONObject.parseObject(JSONObject.toJSONString(JSONObject.parse(body)), PageResult.class);
            PageResult.ResultDTO result = pageResult.getResult();
            List<FinancialMasterEntity> list = JSONArray.parseArray(JSONArray.toJSONString(result.getRecords()), FinancialMasterEntity.class);

            List<FinancialMasterEntity> financialMasterEntities = new ArrayList<>();
            List<FinancialAmountEntity> financialAmountEntities = new ArrayList<>();
            List<FinancialShippingNoteEntity> financialShippingNoteEntities = new ArrayList<>();
            String detailUrl = "http://wlhy.mot.gov.cn/hainan/business/financial/id?id=%s";

            list = list.stream().filter(i -> !shippingIdList.contains(i.getId())).collect(Collectors.toList());
            for (FinancialMasterEntity financialMasterEntity : list) {
                String returnStr = saveDetail(financialMasterEntities, financialAmountEntities, financialShippingNoteEntities, detailUrl, financialMasterEntity);
                if (returnStr != null) return returnStr;
            }
            if (CollectionUtils.isNotEmpty(financialMasterEntities)) {
                financialMasterMapper.insertBatchSomeColumn(financialMasterEntities);
            }
            if (CollectionUtils.isNotEmpty(financialAmountEntities)) {
                financialAmountMapper.insertBatchSomeColumn(financialAmountEntities);
            }
            if (CollectionUtils.isNotEmpty(financialShippingNoteEntities)) {
                financialShippingNoteMapper.insertBatchSomeColumn(financialShippingNoteEntities);
            }

            log.info(String.format("资金单查询，%s到%s，第%s页，总页数%s", startDate, endDate, page, result.getPages()));

        } else if (httpResponse.getStatus() == 203) {
            log.info("登录信息失效");
//            return "返回：登录信息失效";
//            LoginUtils.login();
            return saveAllPri(page, limit, startDate, endDate);
        } else {
            log.info("查询失败");
            return "返回：查询失败";
        }
        log.info("返回：插入成功");
        return "插入成功";
    }

    private String saveDetail(List<FinancialMasterEntity> financialMasterEntities, List<FinancialAmountEntity> financialAmountEntities,
                              List<FinancialShippingNoteEntity> financialShippingNoteEntities, String detailUrl, FinancialMasterEntity financialMasterEntity) {
        log.info("获取资金单详情，id={}", financialMasterEntity.getId());
        HttpResponse httpResponse = HttpUtils.httpGet(String.format(detailUrl, financialMasterEntity.getId()), redisUtils);
        if (httpResponse.getStatus() == 200) {
            String detailBody = httpResponse.body();
            Result detailResult = JSONObject.parseObject(JSONObject.toJSONString(JSONObject.parse(detailBody)), Result.class);
            FinancialDTO financialDTO = JSONObject.parseObject(JSONObject.toJSONString(detailResult.getResult()), FinancialDTO.class);
            FinancialMasterEntity financialMaster = financialDTO.getFinancialMaster();
            financialMasterEntities.add(financialMaster);
            List<FinancialAmountEntity> financialAmount = financialDTO.getFinancialAmount();
            if (CollectionUtil.isNotEmpty(financialAmount)) {
                financialAmount = financialAmount.stream().peek(i -> i.setFinancialId(financialMaster.getId())).collect(Collectors.toList());
                financialAmountEntities.addAll(financialAmount);
            }
            List<FinancialShippingNoteEntity> financialShippingNote = financialDTO.getFinancialShippingNote();
            if (CollectionUtil.isNotEmpty(financialShippingNote)) {
                financialShippingNote = financialShippingNote.stream().peek(i -> i.setFinancialId(financialMaster.getId())).collect(Collectors.toList());
                financialShippingNoteEntities.addAll(financialShippingNote);
            }
        } else if (httpResponse.getStatus() == 203) {
            log.info("登录信息失效");
//                    return "登录信息失效";
//            LoginUtils.login();
            return saveDetail(financialMasterEntities, financialAmountEntities, financialShippingNoteEntities, detailUrl, financialMasterEntity);
        } else {
            log.info("查询失败");
            return "查询失败";
        }
        return null;
    }

}
